import { Prefab, SpriteFrame ,Node} from "cc";
import Singleton from "../Base/Singleton";
import { EntityTypeEnum, IActorMove, IBullet, IClientInput, InputTypeEnum, IRoom, IState, randomBySeed, toFixed } from "../Common";
import { ActorManager } from "../Entity/Actor/ActorManager";
import { JoyStickManager } from "../UI/JoyStickManager";
import { BulletManager } from "../Entity/Bullet/BulletManager";
import EventManager from "./EventManager";
import { EventEnum } from "../Enum";

const ACTOR_SPEED = 100
const BULLET_SPEED = 600

const Map_Width = 960
const Map_Height = 640

const ACTOR_RADIUS=50
const BULLET_RADIUS=10

const BULLET_DAMAGE=5
export default class DataManager extends Singleton {
  static get Instance() {
    return super.GetInstance<DataManager>();
  }
  //玩家id这个id会在游戏登录时给每一个玩家，在创建角色实例时所有脚本都会绑定，导致玩家移动开枪时，其他玩家也在移动开枪，所以需要绑定玩家id
  myPlayerId=1
  
  //房间信息
  roomInfo:IRoom


  //舞台节点
  stage:Node
  //BattleM获取的JoyStickManager脚本
  jm:JoyStickManager
  //保存已经生成的map
  actorMap:Map<number,ActorManager>=new Map()
  bulletMap:Map<number,BulletManager>=new Map()
  //保存在btm异步创建的预制体(loadRes方法)
  prefabMap:Map<string,Prefab>=new Map()
  //保存在btm异步创建的图片(loadRes方法)
  textureMap:Map<string,SpriteFrame[]>=new Map()

  reset() {
    this.frameId = 0;
    this.stage = null;
    this.jm = null;
    this.actorMap.clear();
    this.bulletMap.clear();
    this.prefabMap.clear();
    this.textureMap.clear();
  }

  //帧id，让服务端知道是哪一帧
  frameId=0
  //保存上一次的服务端状态，用来做预测回滚
  lastState:IState
  //描述场景实体的状态
  state:IState ={
    //场景里的角色数组
    actors:[
      // {
      //   id: 2,
      //   nickname: "哈哈1",
      //   position: {
      //     x: -200,
      //     y: -200,
      //   },
      //   direction: {
      //     x: 1,
      //     y: 0,
      //   },
      //   hp: 100,
      //   type: EntityTypeEnum.Actor1,
      //   weaponType: EntityTypeEnum.Weapon1,
      //   bulletType: EntityTypeEnum.Bullet1,
      // },
      // {
      //   id: 1,
      //   nickname: "哈哈2",
      //   position: {
      //     x: 200,
      //     y: 200,
      //   },
      //   direction: {
      //     x: 0,
      //     y: -1,
      //   },
      //   hp: 100,
      //   type: EntityTypeEnum.Actor2,
      //   weaponType: EntityTypeEnum.Weapon2,
      //   bulletType: EntityTypeEnum.Bullet2,
      // },
    ],
    //场景里的子弹数组
    bullets:[],
    nextBulletId:1,
    seed:1,
  }
  /**
   * @param input 客户端输入
   */
  applyInput(input:IClientInput){
    //判断input的类型
    switch(input.type){
      case InputTypeEnum.ActorMove:{
        //修改state
        const {
          id,
          dt,
          direction:{x,y},
        } = input    
        const actor = this.state.actors.find((e)=> e.id === id)
        actor.direction.x = x
        actor.direction.y = y

        actor.position.x += toFixed(x * ACTOR_SPEED * dt)
        actor.position.y += toFixed(y * ACTOR_SPEED * dt) 
        break
      }
      case InputTypeEnum.WeaponShoot:{
        const {
          owner,
          position,
          direction,
        }=input
        //子弹信息
        const bullet:IBullet = {
          id:this.state.nextBulletId++,
          owner,
          position,
          direction,
          type:this.actorMap.get(owner).bulletType,
        }
        //发射子弹的时候改变枪的状态，变成射击动画
        EventManager.Instance.emit(EventEnum.BulletBron,owner)
        //把子弹信息添加到state中
        this.state.bullets.push(bullet)
        break
      }
      case InputTypeEnum.TimePast:{
        const {
          dt,
        }=input
        const {bullets,actors}=this.state

        //子弹碰到边界后删除子弹
        for (let i = bullets.length-1 ; i >= 0; i--){
          const bullet = bullets[i]
          for (let j = actors.length-1; j >=0; j--){      
            const actor = actors[j]           
            //如果子弹碰到角色，触发爆炸效果,扣血
            if((actor.position.x-bullet.position.x)**2 + (actor.position.y-bullet.position.y)**2 < (ACTOR_RADIUS+BULLET_RADIUS)**2){
              //通过伪随机数来算暴击
              const random = randomBySeed(this.state.seed)
              this.state.seed = random
              const damage = random/233280>=0.5?BULLET_DAMAGE*2:BULLET_DAMAGE
              if(damage>BULLET_DAMAGE){
                console.log("暴击！")
              }
              actor.hp -= damage
              //触发爆炸事件
              EventManager.Instance.emit(EventEnum.ExplosionBorn,bullet.id,{
                x: toFixed((actor.position.x+bullet.position.x)/2),
                y: toFixed((actor.position.y+bullet.position.y)/2)
              })
              bullets.splice(i,1)
              break

            }
          }
          if(Math.abs(bullet.position.x) > Map_Width/2 || Math.abs(bullet.position.y) > Map_Height/2){
            //触发爆炸事件
            EventManager.Instance.emit(EventEnum.ExplosionBorn,bullet.id,{x:bullet.position.x,y:bullet.position.y})
            bullets.splice(i,1)
            
          }
        }

        for (const bullet of bullets) {
          bullet.position.x +=toFixed(bullet.direction.x * BULLET_SPEED * dt) 
          bullet.position.y +=toFixed(bullet.direction.y * BULLET_SPEED * dt) 
        }
        break
      }
    }
  }
    
}
